package com.sunbird.crm.base.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName RedisUtils
 * @Descriptiom TODO
 * @Author Sunbird
 * @Date 2019/8/16 9:52
 * @Version 1.0
 **/
@Slf4j
@Component
public class RedisUtils {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * @Author Sunbird
     * @Description 指定缓存失效时间
     * @Date  2019/8/16
     * @Param key 键
     * @Param time 具体时间(秒)
     * @return
     **/
    public boolean expire (String key , long time){
     try {
        if (time > 0){
            redisTemplate.expire(key, time , TimeUnit.SECONDS);
        }
        return  true;
        }catch (Exception e){
         return  false;
     }
    }

    /**
     * @Author Sunbird
     * @Description 根据key 获取过期时间
     * @Date  2019/8/16
     * @Param key 键不能为空
     * @return  返回时间 （秒）  -1 代表永久有效 -2 代表不存在
     **/

    public long getExpire(String key){
        return  redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }
/**
 * @Author Sunbird
 * @Description 判断key 是否存在
 * @Date  2019/8/16
 * @Param key 键
 * @return
 **/
    public boolean hasKey(String key) {
         return  redisTemplate.hasKey(key);
        }

        /**
         * @Author Sunbird
         * @Description 删除缓存
         * @Date  2019/8/16
         * @Param  key 可以使之
         * @return
         **/
        public void del(String... key){
        if (key != null && key.length>0){
            if (key.length==1){
                redisTemplate.delete(key[0]);
            }else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
        }

        //=================String ============
        /**
         * @Author Sunbird
         * @Description  普通缓存获取
         * @Date  2019/8/16
         * @Param  key 键
         * @return 值
         **/

        public Object get(String key){
            return  key == null ? null : redisTemplate.opsForValue().get(key);
    }
    /**
     * @Author Sunbird
     * @Description 普通缓存存放
     * @Date   2019/8/16
     * @Param key  键 value 值
     * @return  成功 、false 失败
     **/

    public boolean set(String key , Object value){
            try{
                redisTemplate.opsForValue().set(key, value);
               return  true;
            }catch (Exception e){
                e.printStackTrace();
                return  false;
            }
    }
    /**
     * @Author Sunbird
     * @Description 普通缓存放入时间并设置时间
     * @Date  2019/8/16
     * @Param  key 键 value 值 time 时间 如果设置时间等于或者小于零 将设置无期限
     * @return
     **/
    public boolean set(String key ,Object vlaue ,long time){
        try{
            if (time > 0){
                redisTemplate.opsForValue().set(key ,vlaue ,time ,TimeUnit.SECONDS);
            }else {
                set(key,vlaue);
            }
            return  true;
        }catch (Exception e){
            e.printStackTrace();
            return  false;
        }

    }
    /**
     * @Author Sunbird
     * @Description 递增
     * @Date  2019/8/16
     * @Param  key 键 delta 要增加多少
     * @return
     **/

    public long incr(String key ,long delta){
        if (delta < 0){
            throw  new RuntimeException("递增因子必须大于0");
        }
        return  redisTemplate.opsForValue().increment(key, delta);
    }
    /**
     * @Author Sunbird
     * @Description 递增
     * @Date  2019/8/16
     * @Param  key 键 delta 要减多
     * @return
     **/
    public long decr(String key ,long delta){
        if (delta < 0){
            throw  new RuntimeException("递减因子必须大于0");
        }
        return  redisTemplate.opsForValue().decrement(key, delta);
    }

    //=====================Map========================
    /**
     * @Author Sunbird
     * @Description HashGet
     * @Date  2019/8/16
     * @Param  key 键 item 项 两者不能为空
     * @return  值
     **/

    public Object hget(String key , String item){
        return  redisTemplate.opsForHash().get(key,item);
    }

    /**
     * @Author Sunbird
     * @Description 获取hashKey 对应的所有的值
     * @Date  2019/8/16
     * @Param  key 键
     * @return  对应的多个键值
     **/

    public Map<Object,Object> hmget(String key){
        return  redisTemplate.opsForHash().entries(key);
    }

    /**
     * @Author Sunbird
     * @Description HashSet
     * @Date  2019/8/16
     * @Param key 键 map 对应多个键值
     * @return
     **/

    public boolean hmset(String key ,Map<String,Object> map){
        try {
            redisTemplate.opsForHash().putAll(key,map);
            return  true;
        }catch (Exception e){
            e.printStackTrace();
            return  false;
        }
    }
    /**
     * @Author Sunbird
     * @Description HashSet
     * @Date  2019/8/16
     * @Param key 键 map 对应多个键值 time 时间（秒）
     * @return
     **/
    public boolean hmset(String key ,Map<String,Object> map,long time){
        try {
            redisTemplate.opsForHash().putAll(key,map);
            if (time >0){
                expire(key, time);
            }
            return  true;
        }catch (Exception e){
            e.printStackTrace();
            return  false;
        }
    }
    /**
     * @Author Sunbird
     * @Description //TODO
     * @Date  2019/8/16
     * @Param key 键 item 项 value 值
     * @return
     **/

    public boolean hset(String key ,String item ,Object value){
        try{
            redisTemplate.opsForHash().put(key,item,value);
            return  true;
        }catch (Exception e){
            e.printStackTrace();
            return  false;
        }
    }
    /**
     * @Author Sunbird
     * @Description 向一张hash表中放入数据，如果不存在将创建
     * @Date  2019/8/16
     * @Param key 键， item 项 , value 值 time 时间 （秒）
     * @return
     **/

    public boolean hset(String key,String item ,Object value ,long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
    * @Author Sunbird
    * @Description //TODO
    * @Date  2019/8/16
    * @Param key 键 item 项 可以多个使用 但不能为null
    * @return
    **/
    public  void hdel(String key , Object... item){
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * @Author Sunbird
     * @Description 判断hash 表中是否有该项的值
     * @Date  2019/8/16
     * @Param
     * @return
     **/

    public boolean hHasKey(String key , String item){
        return  redisTemplate.opsForHash().hasKey(key,item);
    }
        /*
         * @Author Sunbird
         * @Description hash递增 如果不存在,就会创建一个 并把新增后的值返回
         * @Date  2019/8/16
         * @param key 键
         * @param item 项
         * @param by 要增加几(大于0)
         * @return
         **/

    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);

    }
    /*
     * @Author Sunbird
     * @Description hash递增 如果不存在,就会创建一个 并把新增后的值返回
     * @Date  2019/8/16
     * @param key 键
     * @param item 项
     * @param by 要减少几(小于0)
     * @return
     **/
  public double hdecr(String key , String item , double by){
        return redisTemplate.opsForHash().increment(key,item,-by);
  }

  //=====================set=====================
    /**
     * @Author Sunbird
     * @Description 根据key 获取Set 中 的所有值
     * @Date  2019/8/16
     * @Param
     * @return
     **/

    public Set<Object> sGet(String key){
      try{
          return  redisTemplate.opsForSet().members(key);
      }catch (Exception e){
          e.printStackTrace();
          return null;
      }
    }

    /**
     * @Author Sunbird
     * @Description 根据value 从set 中查询是否存在
     * @Date  2019/8/16
     * @Param
     * @return
     **/

    public boolean sHasKey(String key,Object value){
        return  redisTemplate.opsForSet().isMember(key,value);
    }
    /**
     * @Author Sunbird
     * @Description 将数据存入set 缓存
     * @Date  2019/8/16
     * @Param key 键 values 值
     * @return 成功个数
     **/

    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);

        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * @Author Sunbird
     * @Description 将数据存入set 缓存
     * @Date  2019/8/16
     * @Param key 键 values 值 time 时间
     * @return 成功个数
     **/
    public long sSet(String key,long time , Object... values) {
        try {
            long count = 0;
                 count= redisTemplate.opsForSet().add(key, values);
            if (time<0){
                expire(key,time);
            }
                 return count ;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * @Author Sunbird
     * @Description 获取set缓存的长度
     * @Date  2019/8/16
     * @Param 
     * @return 
     **/
    
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * @Author Sunbird
     * @Description 移除值为value 的
     * @Date  2019/8/16
     * @Param
     * @return
     **/

    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    //======================list=========================
    /**
     * @Author Sunbird
     * @Description 获取list 缓存内容
     * @Date  2019/8/16
     * @Param
     * @return
     **/

    public List<Object> lGet(String key ,long start ,long end){
        return  redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 获取list缓存的长度
     * @param key 键
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    /**
     * 通过索引 获取list中的值
     * @param key 键
     * @param index 索引 index>=0时， 0 表头，1 第二个元素，依次类推；index<0时，-1，表尾，-2倒数第二个元素，依次类推
        * @return
     */

    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

        /**
         431
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param
         * @return
         */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
            expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
       /**
\         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
        /**
         * 将list放入缓存
         *
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
            expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
        /**
         * 根据索引修改list中的某条数据
         * @param key 键
         * @param index 索引
         * @param value 值
         * @return
         */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

        /**
         * 移除N个值为value
         * @param key 键
         * @param count 移除多少个
         * @param value 值
         * @return 移除的个数
         */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}
